﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.SQL;
using Wicture.EPC.Common;
using Wicture.EPC.Service.V1.Enum;
using Wicture.EPC.Service.V1.Models;
using Wicture.EPC.Service.V1.Models.LiYang;

namespace Wicture.EPC.Service.V1.Repository
{
    public class BaseQueryInterceptor : IQueryInterceptor
    {
        public virtual string[] BrandCodes { get; } = new string[] { "roewe", "mg" };

        public string _subgroupId = "";

        /// <summary>
        /// 1、逐级选择车型
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object ModelSelector(DbRESTFulRepository repository, JObject param)
        {
            if (string.IsNullOrEmpty(param.Value<string>(ParamFields._id))) param[ParamFields._id] = "0";

            if (param.Value<string>(ParamFields._route) == ParamFields._mainGroup)
            {
                var list = (List<Query_MainGroupResult>)QueryMainGroup(repository, param);
                return new Model_SelectorResult
                {
                    title = "选择主组",
                    items = list
                        .Select(p => new Model_SelectorResult._items { id = p.id.ToString(), code = p.code, name = p.name, hasNext = false, route = "", imageUrl = p.imageUrl })
                        .ToList()
                };
            }
            else
            {
                List<ModelSelector> list = new List<ModelSelector>();
                var type = param.Value<string>(ParamFields._type);
                if (string.IsNullOrEmpty(type))
                {
                    list = (List<ModelSelector>)repository.Invoke<ModelSelector>(CSIs.List_Model_Selector, param);
                    //适应新的修改需求【主组先显示在车型选择中】：如果下一级是mainGroup，则给hasNext赋值为true,便于在车型选择中调用主组选择接口
                    list.Where(e => e.route == ParamFields._mainGroup).ForEach(e => e.hasNext = true);
                }
                else
                {
                    list = (List<ModelSelector>)repository.Invoke<ModelSelector>(CSIs.List_Model_Selector_App, param);
                }

                if (list.Count() < 1) throw new LogicalException($"参数错误", "621");
                if (list.First().name == "选择年款")
                {
                    list = list.OrderByDescending(q => q.objectName).ToList();
                }
                return new Model_SelectorResult
                {
                    title = list[0].name,
                    items = list
                       .Select(p => new Model_SelectorResult._items { id = p.id.ToString(), code = p.objectCode, name = p.objectName, hasNext = p.hasNext, route = p.route, description = p.description })
                       .ToList()
                };
            }
        }


        /// <summary>
        /// 2、查询主组
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QueryMainGroup(DbRESTFulRepository repository, JObject param)
        {
            string currentMainGroupId = "";

            List<Query_MainGroupResult> list = null;
            var vin = param.Value<string>(ParamFields._vin);
            var id = param.Value<string>(ParamFields._id);
            var selectorId = param.Value<string>(ParamFields._selectorId);
            if (!string.IsNullOrEmpty(selectorId) && selectorId != id)
            {
                currentMainGroupId = id;
            }
            else
            {
                selectorId = id;
            }
            param[ParamFields._selectorId] = selectorId;
            list = GetMainGroup(repository, param);
            list = FilterMainGroupsByVin(repository, list, vin);
            list.Where(e => e.id == currentMainGroupId).ForEach(e => e.isSelected = true);
            return list;
        }
        protected virtual List<Query_MainGroupResult> GetMainGroup(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_MainGroupResult>(CSIs.Query_Main_Group_For_SelectorId, param);
        }

        /// <summary>
        /// 3、查询子组
        /// </summary>  
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QuerySubGroup(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();

            List<Query_SubGroupResult> subGroups = GetSubGroup(repository, param).ToList();
            foreach (var item in subGroups)
            {
                item.belongTo = true;
            }

            subGroups = FilterSubGroupsByVin(repository, subGroups, param);
            subGroups = BuildSubGroupResults(subGroups);
            return subGroups;
        }

        /// <summary>
        /// 4、查询零件列表（通过子组或vin码）
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QueryParts(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            string vin = param.Value<string>(ParamFields._vin);
            string selectorId = param.Value<string>(ParamFields._selectorId);
            _subgroupId = param.Value<string>(ParamFields._id);

            List<Query_PartsResult> result = GetParts(repository, param);
            FilterPartsByVin(repository, ref result, vin, selectorId);
            result = BuildPartResults(result);
            return result;
        }
        protected virtual List<Query_PartsResult> GetParts(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_PartsResult>(CSIs.Query_Parts_For_Roewe, param);
        }

        protected virtual IEnumerable<Query_SubGroupResult> GetSubGroup(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<Query_SubGroupResult>(CSIs.Query_SubGroup, param);
        }
        protected virtual List<Query_SubGroupResult> BuildSubGroupResults(List<Query_SubGroupResult> result)
        {
            return result;
        }
        protected virtual List<Query_PartsResult> BuildPartResults(List<Query_PartsResult> result)
        {
            foreach (var item in result)
            {
                if (!string.IsNullOrEmpty(item.hand) && item.hand != "N/A")
                {
                    item.modelNotes = item.hand;
                }
            }
            return result;
        }

        protected virtual List<Query_MainGroupResult> FilterMainGroupsByVin(DbRESTFulRepository repository, List<Query_MainGroupResult> results, string vin)
        {
            return results;
        }

        protected virtual List<Query_SubGroupResult> FilterSubGroupsByVin(DbRESTFulRepository repository, List<Query_SubGroupResult> results, JObject param)
        {
            var vin = param.Value<string>(ParamFields._vin);
            if (string.IsNullOrEmpty(vin) || results == null || results.Count == 0)
            {
                return results;
            }
            dynamic vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code, new { vin });
            if (vinInfo == null)
            {
                throw new LogicalException("vin不存在!", 602);
            }

            IEnumerable<dynamic> filters = repository.Invoke(CSIs.Get_Vin_Usage_Filter_For_Roewe, new { vinInfo.vinFeatureId, vinInfo.modelId });
            HashSet<string> setCodes = new HashSet<string>(filters.Select(q => (string)q.ucCode));
            if (!setCodes.Any())
            {
                return results;
            }


            IEnumerable<dynamic> subGroupFilters = repository.Invoke(CSIs.Get_Subgroup_Uccodes_For_Roewe, new { subGroupIds = results.Select(q => q.id) });
            Dictionary<string, IEnumerable<string>> filterDic = subGroupFilters.GroupBy(q => q.subGroupId).ToDictionary(k => (string)k.Key.ToString(), v => v.Select(x => (string)x.ucCodes).Distinct());
            foreach (var item in results)
            {
                if (!filterDic.ContainsKey(item.id))
                {
                    item.belongTo = false;
                    continue;
                }
                var filterValues = filterDic[item.id];
                if (filterValues.Any(q => string.IsNullOrEmpty(q)))
                {
                    item.belongTo = true;
                    continue;
                }

                var pass = false;
                foreach (var usCodeStr in filterValues)
                {
                    var ucCodes = usCodeStr.Split(',');
                    foreach (var ucCode in ucCodes)
                    {
                        if (setCodes.Contains(ucCode))
                        {
                            pass = true;
                            break;
                        }
                    }
                    if (pass)
                    {
                        break;
                    }
                }
                item.belongTo = pass;
            }

            return results;
        }
        protected virtual void FilterPartsByVin(DbRESTFulRepository repository, ref List<Query_PartsResult> result, string vin, string selectorId)
        {
            if (string.IsNullOrEmpty(vin))
            {
                return;
            }
            dynamic vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code, new { vin });
            if (vinInfo == null)
            {
                throw new LogicalException("vin不存在!", 612);
            }

            IEnumerable<dynamic> filters = repository.Invoke(CSIs.Get_Vin_Usage_Filter_For_Roewe, new { vinInfo.vinFeatureId, vinInfo.modelId });
            HashSet<string> setCodes = new HashSet<string>(filters.Select(q => (string)q.ucCode));
            if (!setCodes.Any())
            {
                return;
            }

            foreach (var item in result)
            {
                if (!item.belongToVin)
                {
                    continue;
                }
                if (string.IsNullOrEmpty(item.featureCodes))
                {
                    continue;
                }
                var ucCodes = item.featureCodes.Split(',');

                var pass = false;
                foreach (var ucCode in ucCodes)
                {
                    if (setCodes.Contains(ucCode))
                    {
                        pass = true;
                        break;
                    }
                }
                item.belongToVin = pass;
            }
        }

        /// <summary>
        /// 5、获取配件详情
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QueryPartDetail(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partId = param.Value<string>(ParamFields._partId);
            dynamic data = null;
            if (string.IsNullOrEmpty(partId))
            {
                data = repository.Invoke(CSIs.Get_Part_Detail, param);
            }
            else
            {
                data = repository.Invoke(CSIs.Get_Usage_Detail, param);
            }
            if (data == null) return null;
            // 1、基本信息赋值
            Query_Part_DetailResult result = JObject.FromObject(data).ToObject<Query_Part_DetailResult>();

            result.replacements = new List<Query_Part_DetailResult._replacement>();
            //3.替换件处理
            if (!string.IsNullOrEmpty(data.partReplacePartCodes))
            {
                List<Query_Part_DetailResult._replacement> replacements = repository.Invoke<Query_Part_DetailResult._replacement>(CSIs.Query_Parts_By_Codes, new { partCodes = data.partReplacePartCodes.Split(',') });
                var replacement = replacements.FirstOrDefault();
                if (replacement != null)
                {
                    replacement.brandCode = brandCode;
                    replacement.brandName = BrandDictionary.GetName(brandCode);
                    replacement.props = new List<Query_Part_DetailResult._prop>();
                    replacement.props.Add(new Query_Part_DetailResult._prop { key = "替换级别", value = "零件级" });
                    replacement.props.Add(new Query_Part_DetailResult._prop { key = "替换类型", value = data.partInterchangeType });
                    if (replacement.disabled.HasValue)
                    {
                        replacement.props = new List<Query_Part_DetailResult._prop>();
                        replacement.props.Add(new Query_Part_DetailResult._prop { key = "是否禁用", value = replacement.disabled.HasValue ? (replacement.disabled.Value ? "是" : "否") : "" });
                    }
                    result.replacements.Add(replacement);
                }
            }
            if (!string.IsNullOrEmpty(data.usageReplacePartCodes))
            {
                List<Query_Part_DetailResult._replacement> replacements = repository.Invoke<Query_Part_DetailResult._replacement>(CSIs.Query_Parts_By_Codes, new { partCodes = data.usageReplacePartCodes.Split(',') });
                var replacement = replacements.FirstOrDefault();
                if (replacement != null)
                {
                    replacement.brandCode = brandCode;
                    replacement.brandName = BrandDictionary.GetName(brandCode);
                    replacement.props = new List<Query_Part_DetailResult._prop>();
                    replacement.props.Add(new Query_Part_DetailResult._prop { key = "替换级别", value = "LOU级" });
                    replacement.props.Add(new Query_Part_DetailResult._prop { key = "替换类型", value = data.usageInterchangeType });
                    if (replacement.disabled.HasValue)
                    {
                        replacement.props = new List<Query_Part_DetailResult._prop>();
                        replacement.props.Add(new Query_Part_DetailResult._prop { key = "是否禁用", value = replacement.disabled.HasValue ? (replacement.disabled.Value ? "是" : "否") : "" });
                    }
                    result.replacements.Add(replacement);
                }
            }


            //4.配件附加属性处理
            var props = new List<Query_Part_DetailResult._prop>
            {
                new Query_Part_DetailResult._prop { key = "件数", value = result.quantity ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "备注", value = result.remark ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "生效日期", value = result.firstYear?.ToString() },
                new Query_Part_DetailResult._prop { key = "有效日期", value = result.lastYear?.ToString() }
            };
            result.props = props.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
            return result;
        }

        /// <summary>
        /// 6.查询热点信息
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QueryHotPoints(DbRESTFulRepository repository, JObject param)
        {
            if (param[ParamFields._selectorId] == null) param[ParamFields._selectorId] = 0;
            IEnumerable<dynamic> data = GetHotPoints(repository, param);
            if (data == null || data.Count() == 0) return null;
            return new
            {
                imgs =
                data.Where(x => !string.IsNullOrEmpty(x.url)).GroupBy(q => q.url).Select(x => new Query_HotPointsResult._imgs
                {
                    url = x.Key,
                    points = JArray.FromObject(x).ToObject<List<Query_HotPointsResult._imgs._points>>()
                })
            };
        }

        protected virtual IEnumerable<dynamic> GetHotPoints(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke(CSIs.Query_HotPoints, param);
        }

        protected virtual dynamic QueryVinByCode(DbRESTFulRepository repository, Get_Model_InfoParam param)
        {
            return repository.Invoke(CSIs.Query_Vin_By_Code, param);
        }
        protected virtual List<Get_Model_InfoResult._props> GetVinProps(DbRESTFulRepository repository, dynamic vin)
        {
            return null;
        }

        protected virtual List<Get_Model_InfoResult._features> GetVinFeatures(DbRESTFulRepository repository, dynamic vin)
        {
            string featureCodes = vin.featureCodes;
            if (!string.IsNullOrEmpty(featureCodes))
            {
                List<Get_Model_InfoResult._features> retList = new List<Get_Model_InfoResult._features>();
                var featureCodeList = featureCodes.Split(",");
                IEnumerable<Feature> features = repository.Invoke<Feature>(CSIs.Query_Vin_Features, new { featureCodes = featureCodeList });
                foreach (var feature in features)
                {
                    retList.Add(new Get_Model_InfoResult._features() { key = feature.featureName, value = feature.description });
                }
                return retList;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 7.指定车型的详细信息
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QueryModel(DbRESTFulRepository repository, JObject param)
        {
            Get_Model_InfoParam modelParam = param.ToObject<Get_Model_InfoParam>();
            Get_Model_InfoResult result = new Get_Model_InfoResult();
            if (!string.IsNullOrEmpty(modelParam.vin))
            {
                var vin = QueryVinByCode(repository, modelParam);
                if (vin == null)
                {
                    throw new LogicalException($"未找到该Vin码:{modelParam.vin}", 610);
                }
                result = BuildVinResult(vin);
                result.props = GetVinProps(repository, vin);
                result.features = GetVinFeatures(repository, vin);
            }
            else
            {
                var ids = modelParam.id.Split("_");
                if (ids.Count() > 1)
                {
                    modelParam.id = ids[1];
                }
                var model = repository.Invoke(CSIs.Get_Model, modelParam);
                if (model != null)
                {
                    result = JObject.FromObject(model).ToObject<Get_Model_InfoResult>();
                    result.props = GetModelProps(repository, param);
                }
            }
            return result;
        }

        public virtual object OnlineQueryVin(DbRESTFulRepository repository, JObject param)
        {
            return null;
        }
        protected virtual Get_Model_InfoResult BuildVinResult(dynamic vin)
        {
            return JObject.FromObject(vin).ToObject<Get_Model_InfoResult>();
        }

        protected virtual List<Get_Model_InfoResult._props> GetModelProps(DbRESTFulRepository repository, JObject param)
        {
            var ret = new List<Get_Model_InfoResult._props>();
            List<Query_CrumbResult> list = repository.Invoke<Query_CrumbResult>(CSIs.Get_Crumbs_App, param);
            foreach (var info in list)
            {
                if (string.IsNullOrEmpty(info.id))
                {
                    continue;
                }
                if (info.fieldCode == "model")
                {
                    ret.Add(new Get_Model_InfoResult._props { key = "厂商", value = info.name.Split('@')[0] });
                    ret.Add(new Get_Model_InfoResult._props { key = "车型", value = info.name.Split('@')[1] });
                }
                else
                {
                    ret.Add(new Get_Model_InfoResult._props { key = info.fieldName?.Replace("选择", ""), value = info.name });
                }
            }
            return ret;
        }

        protected virtual SubGroupInfo GetSubGroupForCrumb(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke<SubGroupInfo>(CSIs.Get_SubGroup_By_Id, param);
        }

        protected virtual dynamic GetMainGroupForCrumb(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke(CSIs.Get_MainGroup_By_Id, param);
        }
        /// <summary>
        /// 获取面包屑导航栏
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object GetCrumbs(DbRESTFulRepository repository, JObject param)
        {
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var selectorId = param.Value<string>(ParamFields._selectorId);
            var id = param.Value<string>(ParamFields._id);
            var vinCode = param.Value<string>(ParamFields._vin);
            var route = param.Value<string>(ParamFields._route);
            List<Query_CrumbResult> result = new List<Query_CrumbResult>();
            if (route == ParamFields._subGroup)
            {
                SubGroupInfo subGroupInfo = GetSubGroupForCrumb(repository, param);
                if (string.IsNullOrEmpty(vinCode))
                {
                    result = repository.Invoke<Query_CrumbResult>(CSIs.Get_Crumbs, new { id = selectorId, brandCode });
                }
                result.Add(new Query_CrumbResult { id = subGroupInfo.mainGroupId, code = subGroupInfo.mainGroupCode, name = subGroupInfo.mainGroupName, fieldCode = ParamFields._mainGroup, fieldName = "主组", step = 100, selectorId = selectorId });
                result.Add(new Query_CrumbResult { id = subGroupInfo.id, code = subGroupInfo.subGroupCode, name = subGroupInfo.subGroupName, fieldCode = ParamFields._subGroup, fieldName = "分组", step = 101, selectorId = selectorId });
            }
            else if (route == ParamFields._mainGroup)
            {
                var mainGroupInfo = GetMainGroupForCrumb(repository, param);
                if (string.IsNullOrEmpty(vinCode))
                {
                    result = repository.Invoke<Query_CrumbResult>(CSIs.Get_Crumbs, new { id = selectorId, brandCode });
                }
                result.Add(new Query_CrumbResult { id = id, code = mainGroupInfo.mainGroupCode.ToString(), name = mainGroupInfo.mainGroupName, fieldCode = ParamFields._mainGroup, fieldName = "主组", step = 100, selectorId = selectorId });
            }
            else if (route == "catalog")
            {
                if (string.IsNullOrEmpty(vinCode))
                {
                    result = repository.Invoke<Query_CrumbResult>(CSIs.Get_Crumbs, new { id = selectorId ?? id, brandCode });
                    result.Last().selectorId = selectorId ?? id;
                }
            }
            else
            {
                if (!string.IsNullOrEmpty(id))
                {
                    result = repository.Invoke<Query_CrumbResult>(CSIs.Get_Crumbs, param);
                }

            }
            if (string.IsNullOrEmpty(vinCode))
            {
                result.Insert(0, new Query_CrumbResult { code = brandCode, name = BrandDictionary.GetName(brandCode), step = 0, fieldCode = ParamFields._brandCode, fieldName = "选择品牌" });
            }
            return result;
        }



        /// <summary>
        /// EPC内零件搜索
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object SearchParts(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var selectorId = param.Value<string>(ParamFields._selectorId);
            var partCodes = param.Value<string>("partCodes");
            var vin = param.Value<string>(ParamFields._vin);
            List<SearchSubGroupResults> searchResults = GetSearchResults(repository, brandCode, partCodes.Split(','), selectorId);
            List<Query_MainGroupResult> mainGroups = searchResults.Select(q => new { q.mainGroupCode, q.mainGroupName }).Distinct().Select(x => new Query_MainGroupResult { id = x.mainGroupCode, code = x.mainGroupCode, name = x.mainGroupName, isBelongTo = true }).ToList();
            List<Query_SubGroupResult> subGroups = searchResults.Select(x => new Query_SubGroupResult { code = x.subGroupCode, belongTo = true, imageSN = x.imageSN, imageUrl = x.imageUrl, mainGroupId = x.mainGroupCode, mainGroupCode = x.mainGroupCode, name = x.subGroupName, id = x.subGroupId, applicableModel = x.applicableModel, remark = x.remark, startTime = x.startTime, endTime = x.endTime, subgroupFilterCode = x.subgroupFilterCode, specCodes = x.specCodes }).ToList();
            subGroups = FilterSubGroupsByVin(repository, subGroups, param);
            subGroups = BuildSubGroupResults(subGroups);
            return new SearchPartsResult { mainGroups = mainGroups, subGroups = subGroups };
        }

        protected virtual List<SearchSubGroupResults> GetSearchResults(DbRESTFulRepository repository, string brandCode, string[] partCodes, string selectorId)
        {
            return repository.Invoke<SearchSubGroupResults>(CSIs.Search_SubGroups_By_PartCodes, new { brandCode, partCodes, selectorId });
        }

        /// <summary>
        /// 检查图片的路径是否有效
        /// </summary>
        /// <param name="param"></param>
        public virtual void CheckSubGroupImage(DbRESTFulRepository repository, JObject param)
        {
            string tableName = param.Value<string>("type");
            IEnumerable<dynamic> list = null;
            switch (tableName)
            {
                case "sub_group":
                    list = repository.Invoke(CSIs.List_sub_group, null);
                    break;
                case "model":
                    list = repository.Invoke(CSIs.List_all_model, null);
                    break;
            }

            foreach (var item in list)
            {
                if (string.IsNullOrEmpty(item.imageUrl)) continue;

                string url = item.imageUrl;
                try
                {
                    Uri uri = new Uri(url);
                    WebRequest req = WebRequest.Create(uri);
                    var rsp = req.GetResponse();
                }
                catch (Exception)
                {
                    //文件不存在，清空图片路径字段
                    switch (tableName)
                    {
                        case "sub_group":
                            repository.Invoke(CSIs.Update_sub_group_image, new { item.id });
                            break;
                        case "model":
                            repository.Invoke(CSIs.Update_model_image, new { item.id });
                            break;
                    }
                }
            }

        }

        public virtual object QueryVins(DbRESTFulRepository repository, JObject param)
        {
            throw new NotImplementedException();
        }

        public virtual object QueryFitModels(DbRESTFulRepository repository, JObject param)
        {
            var pageIndex = param.Value<int>(ParamFields._pageIndex);
            var pageSize = 20;
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partCode = param.Value<string>(ParamFields._partCode);
            var model = GetModelsByPart(repository, pageIndex, pageSize, brandCode, partCode);
            if (model == null) return null;
            Query_FitModelsResult result = JObject.FromObject(model).ToObject<Query_FitModelsResult>();
            if (result == null || result.items == null || !result.items.Any())
            {
                return result;
            }
            var hotPointsModel = GetHotPointsByPart(repository, brandCode, partCode, result.items.Select(q => q.imageId).Distinct());
            JArray allPoints = JArray.FromObject(hotPointsModel);
            foreach (var item in result.items)
            {
                //2.1适用车型多张图片处理
                var imgs = allPoints.Where(p => p.Value<string>(ParamFields._imageId) == item.imageId).Select(p => p.ToObject<Query_FitModelsResult._models._imgs>()).GroupBy(q => new { q.imageId, q.url }).Select(q => new Query_FitModelsResult._models._imgs { imageId = q.Key.imageId, url = q.Key.url }).ToList();
                foreach (var img in imgs)
                {
                    //2.1.1适用车型每张图片对应的热点处理
                    img.points = allPoints.Where(p => p.Value<string>("url") == img.url && p.Value<string>(ParamFields._imageId) == img.imageId)
                                       .Select(p => p.ToObject<Query_FitModelsResult._models._imgs._points>()).ToList();
                }
                item.imgs = imgs.Where(p => p.points.Count > 0).ToList();
                item.imageUrl = item.imgs.FirstOrDefault()?.url;
            }
            return result;
        }

        /// <summary>
        /// pageIndex从1开始
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="brandCode"></param>
        /// <param name="partCode"></param>
        /// <returns></returns>
        protected virtual dynamic GetModelsByPart(DbRESTFulRepository repository, int pageIndex, int pageSize, string brandCode, string partCode)
        {
            return repository.Invoke(CSIs.Query_Models_By_Part, new { pageIndex, pageSize, brandCode, partCode });
        }

        protected virtual dynamic GetHotPointsByPart(DbRESTFulRepository repository, string brandCode, string partCode, IEnumerable<string> imageIds)
        {
            return repository.Invoke(CSIs.Query_HotPoints_By_Part, new { brandCode, partCode, imageIds });
        }

        /// <summary>
        /// 根据力洋车型获取epc车型
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object ModelSelectorByLiYang(DbRESTFulRepository repository, JObject param)
        {
            Get_Model_InfoResult result = null;

            LiYangInfo info = param.ToObject<LiYangInfo>();
            string vin = info.vin;
            var liyangVinInfo = repository.Invoke(CSIs.Get_LiYang_Vin, new { vin });
            if (liyangVinInfo != null)
            {
                LiYangInfo liyangData = JsonConvert.DeserializeObject<LiYangInfo>(liyangVinInfo.liyangData);
                liyangData.vin = info.vin;
                liyangData.selectorId = info.selectorId;
                info = liyangData;
            }

            List<Get_Model_InfoResult> list = repository.Invoke<Get_Model_InfoResult>(CSIs.Query_Model_By_LiYang, info);
            if (list != null && list.Any())
            {
                string liyangModelName = info.Models;
                result = list.FirstOrDefault(e => e.liyangModelName == liyangModelName);
                if (result == null)
                {
                    result = list.FirstOrDefault(e => string.IsNullOrEmpty(e.liyangModelName));
                }
                if (result != null)
                {
                    result.vin = vin;
                    result.warning = "注意：此车架号只解析到车型，请仔细核对";
                    result.props = GetProps(info, result.engineName, result.name);
                }
            }
            return result;
        }
        public virtual object QueryAllPartsByVin(DbRESTFulRepository epcRepository, JObject param)
        {
            throw new NotImplementedException();
        }

        protected PartCatalog MergePartCatalog(PartCatalog partCatalog, MaintainPart maintainPart)
        {
            PartCatalog info = partCatalog.Copy();
            info.standardCode = maintainPart.standardCode;
            info.standardName = maintainPart.standardName;
            return info;
        }

        protected virtual List<MaintainPart> GetMaintainParts(DbRESTFulRepository repository, string selectorId)
        {
            List<MaintainPart> maintainParts = repository.Invoke<MaintainPart>(CSIs.Query_Maintain_Parts_By_SelectorId, new { selectorId });
            return maintainParts;
        }

        public virtual object QueryMaintainParts(DbRESTFulRepository repository, JObject param)
        {
            string vinCode = param.Value<string>(ParamFields._vin);
            string brandCode = param.Value<string>(ParamFields._brandCode);
            string selectorId = param.Value<string>(ParamFields._selectorId);
            List<MaintainPart> maintainParts = GetMaintainParts(repository, selectorId);

            if (!maintainParts.Any())
            {
                return null;
            }
            List<PartCatalog> PartCatalog = GetPartCatalogs(repository, maintainParts.Select(q => q.partCode).Distinct(), selectorId, brandCode, vinCode);

            PartCatalog = (from p in PartCatalog
                           join m in maintainParts on p.partCode equals m.partCode
                           select MergePartCatalog(p, m)).ToList();
            return PartCatalog;
        }

        protected virtual List<PartCatalog> GetPartCatalogs(DbRESTFulRepository repository, IEnumerable<string> partCodes, string selectorId, string brandCode, string vinCode)
        {
            List<PartCatalogResult> partCatalogResults = repository.Invoke<PartCatalogResult>(CSIs.Query_Part_Catalog, new { selectorId, partCodes });
            partCatalogResults = partCatalogResults.GroupBy(q => q.partCode).Select(q => q.First()).ToList();
            var hotPointsModel = repository.Invoke(CSIs.Query_HotPoints_By_Parts, new { brandCode, partIds = partCatalogResults.Select(q => q.id).Distinct() });
            JArray allPoints = JArray.FromObject(hotPointsModel);

            foreach (var item in partCatalogResults)
            {
                //2.1适用车型多张图片处理
                var imgs = allPoints.Where(p => p.Value<string>("partId") == item.id).Select(p => p.Value<string>("url")).Distinct().Select(x => new _imgs { url = x }).ToList();
                foreach (var img in imgs)
                {
                    //2.1.1适用车型每张图片对应的热点处理
                    img.points = allPoints.Where(p => p.Value<string>("url") == img.url && p.Value<string>("partId") == item.id)
                                       .Select(p => p.ToObject<_imgs._points>()).ToList();
                }
                item.imgs = imgs;
            }
            return BuildPartCatalogList(partCatalogResults);
        }

        protected List<PartCatalog> BuildPartCatalogList(List<PartCatalogResult> partCatalogResults)
        {
            List<PartCatalog> retList = new List<PartCatalog>();
            var dic = partCatalogResults.GroupBy(x => x.partCode).ToDictionary(k => k.Key, v => v.ToList());
            foreach (var partCode in dic.Keys)
            {

                var list = dic[partCode];
                var first = list.First();
                PartCatalog info = new PartCatalog()
                {
                    partCode = partCode,
                    marketCode = first.marketCode,
                    marketName = first.marketName,
                    partName = first.partName,
                    price = first.price,
                    cost = first.cost,
                    disabled = first.disabled,
                    priceFC = first.priceFC,
                    priceUpdatedAt = first.priceUpdatedAt,
                    replacedPartCodes = first.replacedPartCodes,
                    notes = string.Join(",", list.Where(x => !string.IsNullOrEmpty(x.notes)).Select(x => x.notes).Distinct())
                };

                info.groups = list.Select(q => new PartCatalog._group
                {
                    partId = q.id,
                    imageSN = q.imageSN,
                    mainGroupCode = q.mainGroupCode,
                    mainGroupId = q.mainGroupId,
                    mainGroupName = q.mainGroupName,
                    selectorId = q.selectorId?.ToString(),
                    subGroupCode = q.subGroupCode,
                    subGroupId = q.subGroupId.ToString(),
                    subGroupName = q.subGroupName,
                    imgs = q.imgs,
                    sn = q.sn
                }).ToList();
                retList.Add(info);
            }

            return retList;
        }

        /// <summary>
        /// 实时查询零件价格
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object RealTimeQueryPartPrice(DbRESTFulRepository repository, JObject param)
        {
            return null;
        }

        /// <summary>
        /// 快速找件
        /// </summary>
        /// <param name="repository"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual object QuickQueryParts(DbRESTFulRepository repository, JObject param)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            string brandCode = param.Value<string>(ParamFields._brandCode);
            string partCodes = param.Value<string>(ParamFields._partCodes);
            string vin = param.Value<string>(ParamFields._vin);
            int selectorId = param.Value<int>(ParamFields._selectorId);
            if (!CheckQuickQueryPartsParam(brandCode, partCodes))
            {
                return ret;
            }

            IEnumerable<string> allPartCodes = GetSpcByPartCodes(repository, partCodes);
            if (allPartCodes != null && allPartCodes.Any())
            {
                ret = QuickQueryParts(repository, allPartCodes, brandCode);
                ret = QuickQueryPartsFilterByMarket(repository, ret, selectorId);
                ret = QuickQueryPartsFilterByUsage(repository, ret, vin, selectorId);
            }
            return ret;
        }
        protected virtual List<QuickPartResult> QuickQueryParts(DbRESTFulRepository repository, IEnumerable<string> partCodes, string brandCode)
        {
            return repository.Invoke<QuickPartResult>(CSIs.Query_QuickParts, new { partCodes = partCodes, brandCode }); ;
        }

        protected virtual List<QuickPartResult> QuickQueryPartsFilterByMarket(DbRESTFulRepository repository, List<QuickPartResult> parts, int selectorId)
        {
            return parts;
        }

        List<QuickPartResult> QuickQueryPartsFilterByUsage(DbRESTFulRepository repository, List<QuickPartResult> parts, string vin, int selectorId)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            //车型下的快速找件
            if (string.IsNullOrEmpty(vin))
            {
                ret = QuickQueryPartsFilterByUsage_Model(repository, parts, selectorId);
            }
            //vin下快速找件
            else
            {
                ret = QuickQueryPartsFilterByUsage_Vin(repository, parts, selectorId, vin);
            }
            return ret;
        }

        protected virtual List<QuickPartResult> QuickQueryPartsFilterByUsage_Vin(DbRESTFulRepository repository, List<QuickPartResult> parts, int selectorId, string vin)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            if (!string.IsNullOrEmpty(vin) && parts != null && parts.Any())
            {
                List<string> partCodes = parts.Select(e => e.partCode).Distinct().ToList();
                List<Query_PartsResult> partUsages = repository.Invoke<Query_PartsResult>(CSIs.Query_Quick_PartUsage_For_Roewe, new { selectorId, partCodes });
                if (partUsages != null && partUsages.Any())
                {
                    List<string> usedPartCodes = new List<string>();

                    HashSet<string> setCodes = new HashSet<string>();
                    dynamic vinInfo = repository.Invoke(CSIs.Query_Quick_Vin_For_Roewe, new { vin });
                    if (vinInfo != null)
                    {
                        IEnumerable<dynamic> filters = repository.Invoke(CSIs.Get_Vin_Usage_Filter_For_Roewe, new { vinInfo.vinFeatureId, vinInfo.modelId });
                        setCodes = new HashSet<string>(filters.Select(q => (string)q.ucCode));
                    }

                    foreach (var item in partUsages)
                    {
                        if (string.IsNullOrEmpty(item.featureCodes))
                        {
                            usedPartCodes.Add(item.partCode);
                            continue;
                        }
                        var ucCodes = item.featureCodes.Split(',');

                        var pass = false;
                        foreach (var ucCode in ucCodes)
                        {
                            if (setCodes.Contains(ucCode))
                            {
                                pass = true;
                                break;
                            }
                        }
                        if (pass)
                        {
                            usedPartCodes.Add(item.partCode);
                        }
                    }

                    if (usedPartCodes.Any())
                    {
                        ret = parts.Where(e => usedPartCodes.Contains(e.partCode)).ToList();
                    }
                }
            }
            return ret;
        }

        protected virtual List<QuickPartResult> QuickQueryPartsFilterByUsage_Model(DbRESTFulRepository repository, List<QuickPartResult> parts, int selectorId)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            if (selectorId > 0 && parts != null && parts.Any())
            {
                List<string> partCodes = parts.Select(e => e.partCode).Distinct().ToList();

                List<Query_PartsResult> partUsages = repository.Invoke<Query_PartsResult>(CSIs.Quick_PartUsage_By_SelectorId, new { selectorId, partCodes });
                if (partUsages != null && partUsages.Any())
                {
                    foreach (var item in parts)
                    {
                        if (partUsages.FirstOrDefault(e => e.partCode == item.partCode) != null)
                        {
                            ret.Add(item);
                        }
                    }
                }
            }
            return ret;
        }

        bool CheckQuickQueryPartsParam(string brandCode, string partCodes)
        {
            bool res = true;
            if (string.IsNullOrEmpty(brandCode) || string.IsNullOrEmpty(partCodes))
            {
                return false;
            }
            var partCodeArr = partCodes.Split(new char[] { ',' });
            if (partCodeArr.Count() > 50)
            {
                return false;
            }

            return res;
        }

        protected virtual IEnumerable<string> GetSpcByPartCodes(DbRESTFulRepository repository, string partCodes)
        {
            List<string> result = new List<string>();
            if (!string.IsNullOrEmpty(partCodes))
            {
                var param = partCodes.Split(new char[] { ',' });
                result.AddRange(param);

                List<string> partList = repository.Invoke<string>(CSIs.Get_Spcs_By_PartCodes, new { partCodes = param });
                if (partList != null && partList.Any())
                {
                    partList.ForEach(e =>
                    {
                        if (!string.IsNullOrEmpty(e))
                        {
                            var tmpPartCodes = e.Split(new char[] { ',' });
                            result.AddRange(tmpPartCodes);
                        }
                    });
                }
            }
            return result.Distinct();
        }

        #region private mothods
        private List<Get_Model_InfoResult._props> GetProps(LiYangInfo param, string engineName, string epcModelName)
        {
            List<Get_Model_InfoResult._props> features = new List<Get_Model_InfoResult._props>();
            features.Add(new Get_Model_InfoResult._props { key = "车型", value = epcModelName });
            features.Add(new Get_Model_InfoResult._props { key = "年款", value = param.Year });
            features.Add(new Get_Model_InfoResult._props { key = "排放标准", value = param.EmissionStandard });
            features.Add(new Get_Model_InfoResult._props { key = "发动机型号", value = param.EngineModel });
            if (!string.IsNullOrEmpty(engineName))
            {
                features.Add(new Get_Model_InfoResult._props { key = "发动机信息", value = engineName });
            }
            features.Add(new Get_Model_InfoResult._props { key = "变速器", value = param.TransmissionDescription });
            features.Add(new Get_Model_InfoResult._props { key = "驱动", value = param.DriveMode });
            return features;
        }


        #region 根据操作环节筛选零件数据（年份、车系等）
        private List<Query_PartsResult> QueryPartsExtend(DbRESTFulRepository repository, List<Query_PartsResult> result, JToken param)
        {
            var selector = repository.Invoke(CSIs.Get_Model_Selector, new { id = param.Value<int>(ParamFields._selectorId) });

            if (selector.filedName == ModelSelectorRouteEnum.year.ToString())
            {
                var selectorYear = int.Parse(selector.objectCode);
                if (selectorYear > 0)
                {
                    result = result.Where(e => (e.firstYear <= selectorYear && e.lastYear >= selectorYear) || (e.firstYear == null || e.lastYear == null)).ToList();
                }
            }

            if (selector.parentId > 0)
            {
                param[ParamFields._selectorId] = selector.parentId;
                result = QueryPartsExtend(repository, result, param);
            }
            return result;
        }


        #endregion

        #endregion
        public virtual object RealTimeQueryOEMStock(DbRESTFulRepository repository, JObject param)
        {
            return null;
        }
    }

}


